package de.tabuma.soap.logik;

import java.util.*;
import java.util.logging.*;
import java.lang.reflect.*;
import de.tabuma.soap.annotation.*;
import javax.xml.namespace.*;

import de.tabuma.soap.entity.*;
import de.tabuma.soap.entity.wsdl.*;

/**
  * @author $Author: alefen $
  * @version $Revision: 1.1 $
  * @since $Date: 2009/12/30 02:53:55 $
 */
public class WsdlFacade {
    
    private static final Logger log = Logger.getLogger(WsdlFacade.class.getName());

    /**
     * @param tDefinitions
     * @return
     */
    public static String getWsdlDocument(TDefinitions tDefinitions) {
        return getWsdl(tDefinitions,0);
    }

    public static String getSoapFieldDefinitionString(SoapFieldDefinition soapFieldDefinition, Field field, Object object, int ebene) {
        log.fine("getSoapFieldDefinitionString; SoapFieldDefinition:"+soapFieldDefinition+"; field="+field+"; object:"+object+";ebene:"+ebene);
        String val = "";
        log.fine("field " + field.getName() + " has type " + field.getType());
        if(field.getType().equals(java.util.List.class)) {
            log.fine("this is list typ");
            try {
                List<Long> list = (List<Long>) object.getClass().getMethod(ObjectMethods.getGetter(field.getName())).invoke(object);
                if(list!=null) {
                    log.fine("list:" + list.size());
                    for(int j=0;j<list.size();j++) {
                        log.fine("count mapping:"+soapFieldDefinition.value().length+"/"+list.get(j));
                        if(soapFieldDefinition.value().length>1) {
                            AnyElement anyElement = PMF.get(list.get(j), new AnyElement());
                            String str = "";
                            for(int kl=0;kl<anyElement.getClass().getDeclaredFields().length;kl++) {
                                Field f = anyElement.getClass().getDeclaredFields()[kl];
                                try {
                                    str += f.getName()+"="+anyElement.getClass().getMethod(ObjectMethods.getGetter(f.getName())).invoke(anyElement)+";";
                                }
                                catch(Exception e) {}
                            }
                            val += getWsdl(anyElement.toObject(),ebene+1);
                        }
                        else {
                            Object object1 = PMF.get(list.get(j), soapFieldDefinition.value()[0].classDefinition().getConstructors()[0].newInstance());
                            log.fine(object1.toString());
                            val += getWsdl(object1, ebene+1);
                        }
                    }
                }
            }
            catch(Exception e) {
                log.warning(e.getMessage()+"/"+e.getCause()+"/"+e.getClass());
                String str = "";
                for(int t1=0;t1<e.getStackTrace().length;t1++) {
                    str += e.getStackTrace()[t1]+"\n";
                }
                log.warning(str);
            }
        }
        else {
            log.fine("this is long typ");
            try {
                Long id = (Long) object.getClass().getMethod(ObjectMethods.getGetter(field.getName())).invoke(object);
                if(id!=null) {
                    if(id.longValue()!=0) {
                        Object object1 = PMF.get(id, soapFieldDefinition.value()[0].classDefinition().getConstructors()[0].newInstance());
                        val += getWsdl(object1, ebene+1);
                    }
                }
            }
            catch(Exception e) {
                log.warning(e.getMessage()+"/"+e.getCause()+"/"+e.getClass());
                String str = "";
                for(int t1=0;t1<e.getStackTrace().length;t1++) {
                    str += e.getStackTrace()[t1]+"\n";
                }
                log.warning(str);
            }
        }
        return val;
    }

    public static String getSoapExtendsDefinitionAttribute(SoapExtendsDefinition soapExtendsDefinition,Field field, Object object, int ebene) {
        log.fine("getSoapExtendsDefinitionAttribute; SoapExtendsDefinition="+soapExtendsDefinition+"; field="+field+"; object:"+object+";ebene:"+ebene);
        String val = "";
        try {
            Long objectId = (Long) object.getClass().getMethod(ObjectMethods.getGetter(field.getName())).invoke(object);
            if(objectId!=null) {
                if(objectId!=0) {
                    Object obj = soapExtendsDefinition.extendsClass().getConstructors()[0].newInstance();
                    obj = PMF.get(objectId, obj);
                    val = ObjectAttributeFacade.getAttribute(obj);
                }
            }
        }
        catch(Exception e) {
            log.warning(e.getMessage()+"/"+e.getCause());
            String warning = "";
            for(int i=0;i<e.getStackTrace().length;i++) {
                warning += e.getStackTrace()[i]+"\n";
            }
            log.warning(warning);
        }

        return val;
    }

    public static String getSoapExtendsDefinition(SoapExtendsDefinition soapExtendsDefinition,Field field, Object object, int ebene) {
        String val = "";
        log.fine("getSoapExtendsDefinition; SoapExtendsDefinition="+soapExtendsDefinition+"; field="+field+"; object:"+object+"; ebene:"+ebene);
        try {
            Long objectId = (Long) object.getClass().getMethod(ObjectMethods.getGetter(field.getName())).invoke(object);
            if(objectId!=null) {
                if(objectId!=0) {
                    log.fine("obj:test1");
                    Object obj = soapExtendsDefinition.extendsClass().getConstructors()[0].newInstance();
                    log.fine("obj:"+obj);
                    obj = PMF.get(objectId, obj);
                    log.fine("obj:"+obj+";id:"+objectId);
                    val = getWsdl(obj, ebene+1);
                }
            }
        }
        catch(Exception e) {
            log.warning(e.getMessage()+"/"+e.getCause());
            String warning = "";
            for(int i=0;i<e.getStackTrace().length;i++) {
                warning += e.getStackTrace()[i]+"\n";
            }
            log.warning(warning);
        }

        return val;
    }

    /**
     * @param object
     * @return
     */
    public static String getWsdl(Object object,int ebene) {
        String value = "";

        if(object==null) {
            log.warning("object ("+object+") is null ");
            return "";
        }

        SoapClassDefinition soapClassDefinition = object.getClass().getAnnotation(SoapClassDefinition.class);
        if(log.getLevel()==Level.FINE || log.getLevel()==Level.FINER || log.getLevel()==Level.FINEST)
        try {
            log.fine("soapClassDefinition " + soapClassDefinition + " of " + object + "(" + ObjectMethods.toString(object) + ")");
        }
        catch(Exception e) {}
        String val = getWhitespace(ebene);

        if(soapClassDefinition!=null) {
            value += val + "<"+soapClassDefinition.value()[0].mappingString();
            for(int i=0;i<object.getClass().getDeclaredFields().length;i++) {
                Field field = object.getClass().getDeclaredFields()[i];
                SoapExtendsDefinition soapExtendsDefinition = field.getAnnotation(SoapExtendsDefinition.class);
                if(soapExtendsDefinition!=null) {
                    value += " " + getSoapExtendsDefinitionAttribute(soapExtendsDefinition, field, object, ebene);
                }
            }
            value += " " + ObjectAttributeFacade.getAttribute(object) + ">\n";
            for(int i=0;i<object.getClass().getDeclaredFields().length;i++) {
                Field field = object.getClass().getDeclaredFields()[i];
                SoapFieldDefinition soapFieldDefinition = field.getAnnotation(SoapFieldDefinition.class);
                if(soapFieldDefinition!=null) {
                    value += getSoapFieldDefinitionString(soapFieldDefinition, field, object, ebene);
                }
                SoapExtendsDefinition soapExtendsDefinition = field.getAnnotation(SoapExtendsDefinition.class);
                if(soapExtendsDefinition!=null) {
                    value += getSoapExtendsDefinition(soapExtendsDefinition, field, object, ebene);
                }
            }
            value += val + "</"+soapClassDefinition.value()[0].mappingString()+">\n";
        }
        else {
            log.fine("objectsize:"+object.getClass().getDeclaredFields().length);
            for(int i=0;i<object.getClass().getDeclaredFields().length;i++) {
                Field field = object.getClass().getDeclaredFields()[i];
                
                SoapFieldDefinition soapFieldDefinition = field.getAnnotation(SoapFieldDefinition.class);
                SoapExtendsDefinition soapExtendsDefinition = field.getAnnotation(SoapExtendsDefinition.class);

                if(soapFieldDefinition!=null || soapExtendsDefinition!=null) {
                    log.fine("field:"+field.getName()+"|"+"soapFieldDefinition:"+soapFieldDefinition+"|"+"soapExtendsDefinition:"+soapExtendsDefinition);
                }
                
                if(soapFieldDefinition!=null) {
                     value += getSoapFieldDefinitionString(soapFieldDefinition, field, object, ebene);
                }
                if(soapExtendsDefinition!=null) {
                    value += getSoapExtendsDefinition(soapExtendsDefinition, field, object, ebene);
                }
            }
        }
        return value;
    }

    /**
     * 
     * @param ebene
     * @return
     */
    private static String getWhitespace(int ebene) {
        String whitespace = "";
        for(int i=0;i<ebene;i++) {
            whitespace += "   ";
        }
        return whitespace;
    }
}